package com.qf.fronted.service.impl;

import com.qf.commons.Data;
import com.qf.fronted.domain.Goods;
import com.qf.fronted.domain.Order;
import com.qf.fronted.domain.WebOrder;
import com.qf.fronted.mapper.*;
import com.qf.fronted.service.IOrderService;
import org.apache.commons.text.RandomStringGenerator;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Transactional
public class OrderServiceImpl2 implements IOrderService {

    private final String imageServerLocation = "http://localhost/images/";

    private OrderMapper orderMapper;

    private GoodMapper goodMapper;

    private CartMapper cartMapper;

    private UserMapper userMapper;

    private TagsMapper tagsMapper;

    public OrderServiceImpl2(OrderMapper orderMapper, GoodMapper goodMapper, CartMapper cartMapper, UserMapper userMapper,TagsMapper tagsMapper) {
        this.orderMapper = orderMapper;
        this.goodMapper = goodMapper;
        this.cartMapper = cartMapper;
        this.userMapper = userMapper;
        this.tagsMapper = tagsMapper;
    }

    @Override
    public void insertOrder(String orderNo, BigDecimal price, Integer num, String goodsImg, String goodsTitle, Integer orderStatus, Integer appraiseStatus, Integer userId, Integer goodId,Date createTime) throws SQLException {
        orderMapper.insertOrder(orderNo,price,num,goodsImg,goodsTitle,orderStatus,appraiseStatus,userId,goodId,createTime);
    }

    @Override
    public void insertOrderAddress(String orderNo, Integer defaultTakeDelivertyAddressId) throws SQLException {
        orderMapper.insertOrderAddress(orderNo,defaultTakeDelivertyAddressId);
    }

    /**
     *  确认订单
     * @param goodsInfo   存储的是用户的商品的id以及商品的购买数量
     * @param defaultTakeDelivertyAddressId  收货地址
     * @param userId  用户id
     * @return
     */
    @Override
    public Data ensureOrder(Map<Integer, Integer> goodsInfo, Integer defaultTakeDelivertyAddressId, Integer userId) {
        /**
         * 1. 首先要判断库存是否充足，更新库存
         * 2. 如果库存充足的情况下，生成订单
         * 3. 插入用户的订单和收获地址
         * 4. 删除购物车数据
         */
        Set<Integer> goodIds = goodsInfo.keySet(); // 获取所有的商品的id

        // 将集合转换一个对应类型的数组
        Integer[] ids = goodIds.toArray(new Integer[goodIds.size()]);

        // 因为订单表中得插入 商品几乎所有的信息
        List<Goods> goodsList = goodMapper.getGoodsByIds(Arrays.asList(ids));

        Data data = null;
//        Connection conn = DbUtils.getConnection();
//        try {
//            conn.setAutoCommit(false);  //事务要手动提交
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }

        //总的价格， 要在前端支付的价格
        BigDecimal totalPrice = BigDecimal.valueOf(0);

        // 需要返回到前端的数据
        Map<String, Object> resultData = new HashMap<>(); // {"totalPrice": , "orderNo": }

        try {
            for (Integer goodId : goodIds) {
//                // 对不同进行上锁
//                synchronized (goodId) {
//                    // 查询的商品的库存
                    Integer stockNum = goodMapper.getStockOfSpecifiedGoods(goodId);

                    // 得到用户需要购买的数量
                    Integer realBuyNum = goodsInfo.get(goodId);

                    // 用户要购买的数量大于实际的库存
                    if (realBuyNum > stockNum) {
//                        try {
//                            conn.rollback();  //如果某件商品商品库存不够，将之前所有的操作全部回滚掉
//                        } catch (SQLException e) {
//                            e.printStackTrace();
//                        } finally {
//                            try {
//                                conn.close();
//                            } catch (SQLException e) {
//                                e.printStackTrace();
//                            }
//                        }
                        data = new Data(-1, "库存不够.");
                        return data;
                    } else {  //库存够用户购买
                        // 如果够的话，就更新库存
                        goodMapper.updateStockNum(stockNum - realBuyNum, goodId);
                    }
                }
//            }

            String oderNo = generateOrderNo(); //获取订单编号
            resultData.put("orderNo", oderNo);

            for (Goods g : goodsList) {
                Integer goodId = g.getGoodId();
                BigDecimal price = g.getPrice(); //商品的价格
                String title = g.getTitle();
                String image = g.getImageSrc();
                Integer num = goodsInfo.get(goodId); //实际购买的商品的数量
                // 插入订单
                orderMapper.insertOrder(oderNo, g.getPrice(), num, image, title, 0, 0, userId, goodId,new Date());

                /**
                 * add()   加上
                 * multiply()  乘法
                 * divide()   除法
                 * subtract() 减法
                 */
                totalPrice = totalPrice.add(price.multiply(BigDecimal.valueOf(num)));
            }

            // 插入订单的收货地址
            orderMapper.insertOrderAddress(oderNo, defaultTakeDelivertyAddressId);

            // 删除用户的购物车数据
            cartMapper.deleteShoppingCartDataOfUser(userId);

//            conn.commit();   //提交事务
        } catch (SQLException e) {
//            e.printStackTrace();
//            try {
//                conn.rollback();
//            } catch (SQLException ex) {
//                ex.printStackTrace();
//            }
            data = new Data(-2, "提交订单失败");
            return data;
        }
//        } finally {
//            try {
//                conn.close();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }

        data = new Data(1, "成功");

        resultData.put("totalPrice", totalPrice);

        data.setObj(resultData);  //设置总的价格

        return data;
    }

    /**
     *  支付成功之后更新订单状态并创建流水
     * @param tNo  支付宝流水号
     * @param orderNo  订单编号
     * @return
     */
    @Override
    public Data updateOrderStatusAndCreateTag(String tNo ,String orderNo,String paymentType) {
        /**
         *      1.修改订单的状态，变为 “已支付”
         *      2.生成支付宝订单流水
         */


        // 查询对应订单编号的所有的订单，目的是为了计算订单的总金额
        List<Order> list = orderMapper.getOrdersOfOrderNo(orderNo);

        // 需要支付的总金额
        BigDecimal totalPrice = BigDecimal.valueOf(0);
        int userId=0;
        // 集合有流处理
        for(Order o : list) {
            BigDecimal price = o.getGoodPrice(); //获取商品的价格
            Integer num = o.getGoodNum(); //获取商品的数量
            userId=o.getUserId();
            // 单个商品的总价格
            BigDecimal singleGoodsTotalPrice = price.multiply(BigDecimal.valueOf(num));

            totalPrice = totalPrice.add(singleGoodsTotalPrice);
        }
        Data data = null;
//        Connection connection = DbUtils.getConnection();
        try {
//            connection.setAutoCommit(false);  //设置事务不自动提交

            //生成支付宝订单流水
            tagsMapper.createTags(tNo,orderNo,totalPrice,userId, LocalDateTime.now(),paymentType);
            // 更新订单的状态，变为已支付
            orderMapper.updateOrderStatus(orderNo, 1,new Date());
//            connection.commit(); //提交事务
        }catch (SQLException ex) {
//            ex.printStackTrace();
//            try {
//                connection.rollback();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
            data = new Data(-2, "修改失败, 请稍后再试.");
            return data;
        }
//        }finally {
//            try {
//                connection.close();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }
//        }
        data = new Data(1, "修改成功");
        return data;
    }

    /**
     * 通过订单状态和用户id获取订单
     * @param status 订单状态 1为已支付，0为未支付，2为已取消或已过期
     * @param userId 用户id
     * @return
     */
    @Override
    public List<WebOrder> getOrdersByStatus(Integer status, Integer userId) {
        List<Order> orderList = orderMapper.getOrdersByStatus(status,userId);
//
        List<WebOrder> webOrderList = new ArrayList<>();

        /**
         * map作用是将订单按照订单编号来分类。key是订单编号，value是拥有相同订单编号的订单.
         */
        Map<String, List<Order>> map = new HashMap<>();

        /**
         * map的作用是存储对应订单的创建日期，key是订单编号，value是订单的创建日期
         */
        Map<String, Date> orderTimeMap = new HashMap<>();

        Map<String, BigDecimal> orderMoneyMap = new HashMap<>();

        for(Order o : orderList) {
            String orderNo = o.getOrderNo(); //订单编号
            Date createTime = o.getCreateTime(); //订单的创建日期
            BigDecimal oneMoney = o.getGoodPrice();//订单单个商品的价格
            BigDecimal oneNum = new BigDecimal(o.getGoodNum());//订单单个商品的数量
            o.setGoodsImg(imageServerLocation + o.getGoodsImg());

            // 获取该订单编号的创建日期
            Date createDate = orderTimeMap.get(orderNo);
            if(null == createDate) {
                orderTimeMap.put(orderNo, createTime);
            }

            //计算该订单的总金额
            BigDecimal money = orderMoneyMap.get(orderNo);
            if(null == money) {
                orderMoneyMap.put(orderNo,oneMoney.multiply(oneNum));
            }else {
                orderMoneyMap.put(orderNo,(oneMoney.multiply(oneNum)).add(money));
            }

            /**
             * [
             *    {orderNo: 1, XXXXX},  map -> {1: list[xxxxx]}
             *    {orderNo: 1, ZZZZ},  map -> {1: list[xxxxx, ZZZZ]}
             *    {orderNo: 2, yyyyy}, map ->{1: list[xxxxx, ZZZZ], 2: list[yyyyy]}
             *    {orderNo: 2, oooo},  map ->{1: list[xxxxx, ZZZZ], 2: list[yyyyy]}
             *    {orderNo: 2, XXXXX},
             * ]
             */
            // 获取该订单编号对应的所有的订单
            List<Order> orders = map.get(orderNo);
            if(null == orders) {  //该订单编号没有对应的订单
                orders = new ArrayList<>();
                orders.add(o);
                map.put(orderNo, orders);
            }else { //该订单编号有订单了
                orders.add(o);
            }
        }


        map.forEach((k, v) -> {
            WebOrder webOrder = new WebOrder();

            webOrder.setOrderNo(k);
            webOrder.setOrders(v);

            Date createTime = orderTimeMap.get(k);  //订单的创建日期

            webOrder.setCreateTime(orderTimeMap.get(k));

            webOrder.setOrderMoney(orderMoneyMap.get(k));

            webOrderList.add(webOrder);
        });

        return webOrderList;
    }

    /**
     *  根据订单编号查询订单
     * @param orderNo 订单编号
     * @return
     */
    @Override
    public List<Order> getOrdersOfOrderNo(String orderNo) {
        List<Order> orderList = orderMapper.getOrdersOfOrderNo(orderNo);
        orderList.forEach(o -> {
            String imageSrc = (o.getGoodsImg());
            o.setGoodsImg(imageServerLocation + imageSrc);
        });
        return orderList;
    }

    @Override
    public void changeOrderByOrderNo(String orderNo) {
        orderMapper.changeOrderByOrderNo(orderNo);
    }

    /**
     *  根据订单编号取消订单,并改变订单状态
     * @param orderNo
     */
    @Override
    public void deleteOrderByOrderNo(String orderNo) {
        orderMapper.deleteOrderByOrderNo(orderNo);
    }

    /**
     * 生成订单号： 按照 年月日十分秒毫秒 + 6位随机码
     *
     * @return location.href = '订单展示页面.html';
     */
    private String generateOrderNo() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");

        String datePrefix = sdf.format(date);

        RandomStringGenerator generator = new RandomStringGenerator.Builder()
                .withinRange(new char[]{'0', '9'}).build();

        String randomNum = generator.generate(6);

        return datePrefix + randomNum;
    }
}
